#pragma once
#include<string>
#include<iostream>
#include <jsoncpp/json/json.h>


const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";

// Encode函数用于将数据包编码为字符串格式，len\npackage\n
std::string Encode(const std::string &content) 
{
    return std::to_string(content.size()) + protocol_sep + content + protocol_sep;
}

// Decode函数用于将字符串格式的数据包解码为原始数据包
bool Decode(std::string &package,std::string& content) 
{
    size_t pos = package.find(protocol_sep);
    if(pos == std::string::npos) return false; // 没有找到分隔符
    std::string len_str= package.substr(0, pos);
    size_t len = std::stoi(len_str); // 获取包长度
    content = package.substr(pos+1,len);
    size_t total_len = len_str.size()  + len + 2;
    if(package.size() < total_len) 
    {
        return false; // 数据包不完整
    }
    //需要移除报文
    package.erase(0, total_len); // 移除已处理的报文
    return true; // 成功解码
}

//使用json或者protobuf等序列化库来实现数据包的序列化和反序列化
class Request
{
public:
    Request(int x=0, int y=0, char op='+')
        : x_(x), y_(y), op_(op) 
    {
    }

    //struct -> "x op y"
    bool Serialize(std::string &out) 
    {
    #ifdef Myself
        out = std::to_string(x_) + blank_space_sep + op_ + blank_space_sep + std::to_string(y_);
        return true;
    #else
        Json::Value root;
        root["x"] = x_;
        root["y"] = y_;
        root["op"] = std::to_string(op_); 
        Json::StyledWriter writer; // 使用Jsoncpp库的StyledWriter进行格式化输出
        out = writer.write(root);
        return true;
    #endif
    }

    //"x op y" -> struct
    bool Deserialize(const std::string &in) 
    {
    #ifdef Myself
        size_t pos= in.find(blank_space_sep);
        if(pos==std::string::npos) return false;
        std::string x_str = in.substr(0, pos);
        x_ = std::stoi(x_str);
        op_ = in[pos + 1]; // 获取操作符
        pos=in.rfind(blank_space_sep);
        if(pos==std::string::npos) return false;
        std::string y_str = in.substr(pos + 1);
        y_ = std::stoi(y_str);
        return true;
    #else
        Json::Value v;
        Json::Reader r;
        r.parse(in, v);
        x_= v["x"].asInt();
        y_= v["y"].asInt();
        op_ = stoi(v["op"].asString()); 
        return true;
    #endif
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x_ << op_ << y_ << "=?" << std::endl;
    }

    int GetX() const { return x_; }
    int GetY() const { return y_; }
    char GetOp() const { return op_; }
    void SetX(int x) { x_ = x; }
    void SetY(int y) { y_ = y; }
    void SetOp(char op) { op_ = op; }

    ~Request() = default;
private:
    int x_;
    int y_;
    char op_;
};

class Response
{
public:
    Response(int result=0, int code=0)
        : result_(result), code_(code) 
    {
    }

    //struct -> "result code"
    bool Serialize(std::string &out) 
    {
    #ifdef Myself
        out = std::to_string(result_) + blank_space_sep + std::to_string(code_);
        return true;
    #else
        Json::Value root;
        root["result"] = result_;
        root["code"] = code_;
        Json::StyledWriter writer; // 使用Jsoncpp库的StyledWriter进行格式化输出
        out = writer.write(root);
        return true;
    #endif
    }

    //"result code" -> struct
    bool Deserialize(const std::string &in) 
    {
    #ifdef Myself
        size_t pos = in.find(blank_space_sep);
        if(pos == std::string::npos) return false;
        std::string result_str = in.substr(0, pos);
        result_ = std::stoi(result_str);
        std::string code_str = in.substr(pos + 1);
        code_ = std::stoi(code_str);
        return true;
    #else
        Json::Value v;
        Json::Reader r;
        r.parse(in, v);
        result_ = v["result"].asInt();
        code_ = v["code"].asInt();
        return true;
    #endif
    }

    int GetResult() const { return result_; }
    int GetCode() const { return code_; }
    void SetResult(int result) { result_ = result; }
    void SetCode(int code) { code_ = code; }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << result_ << ", code: "<< code_ << std::endl;
    }

    ~Response() = default;
private:
    int result_;
    int code_;// 0: success, 1: error
};